Abraxus's Blog

RaRCTF RaRPG Write Up

Details:

Jeopardy style CTF

Category: Reverse Engineering

Points: 200

Comments:

Challenge instance ready at 193.57.159.27:40052. Click here to request a new instance. I've been building a brand new Massively(?) Multiplayer(?) Online Role-Playing(?) Game(?) - try it out! Just don't try and visit the secret dev room...

If you do not have the linked libraries, download rarpg-libs.zip and extract the libraries into your working directory. Then use LD_LIBRARY_PATH=$(pwd) ./client <ip> <port>

Write up:

Opening up the game and walking around a bit I saw that there was a door behind some walls:

│                X                                                                                  │
│                                                                                                   │
│         ~~~~~~~~~~~~~~~      WWWWWW                                                               │
│X        ~~~~~~~~~~~~~~~   *  W   XW                                                               │
│         ~~~~~~~~~~~~~~~      WWWWWW                                                               │
│                                                                                                   │
│                X                                                                                            

From this I knew that I would most likely need to overwrite some sort of move check so I looked into the function names for something along the lines of move and found the following function:

_BOOL8 __fastcall move_okay(int a1, int a2)
{
  bool v3; 
  int v4; 

  if ( wmove(stdscr__NCURSES6_TINFO_5_0_19991023, a1, a2) == -1 )
    v4 = -1;
  else
    v4 = winch(stdscr__NCURSES6_TINFO_5_0_19991023);
  v3 = 1; // set move to ok
  if ( v4 != 32 ) // if not an empty space we check if its a door or wall
    v3 = v4 == 88; // set move to not ok
  return v3;
}

While running a dynamic analysis I edited the registers so that it wouldn't set the check to false however that took too much time so the server locked me out. I then decided to edit the binary to remove the check for if we hit a wall. For this I took a look at the assembly:

.text:0000000000004970 55                                            push    rbp
.text:0000000000004971 48 89 E5                                      mov     rbp, rsp
.text:0000000000004974 48 83 EC 20                                   sub     rsp, 20h
.text:0000000000004978 89 7D FC                                      mov     [rbp+var_4], edi
.text:000000000000497B 89 75 F8                                      mov     [rbp+var_8], esi
.text:000000000000497E 48 8B 3C 25 A0 D4 41 00                       mov     rdi, 41D4A0h    ; WINDOW *
.text:0000000000004986 8B 75 FC                                      mov     esi, [rbp+var_4] ; int
.text:0000000000004989 8B 55 F8                                      mov     edx, [rbp+var_8] ; int
.text:000000000000498C E8 5F FA FF FF                                call    _wmove
.text:0000000000004991 83 F8 FF                                      cmp     eax, 0FFFFFFFFh
.text:0000000000004994 0F 85 0D 00 00 00                             jnz     loc_49A7
.text:000000000000499A B8 FF FF FF FF                                mov     eax, 0FFFFFFFFh
.text:000000000000499F 89 45 F0                                      mov     [rbp+var_10], eax
.text:00000000000049A2 E9 10 00 00 00                                jmp     loc_49B7
.text:00000000000049A7                               ; ---------------------------------------------------------------------------
.text:00000000000049A7
.text:00000000000049A7                               loc_49A7:                               ; CODE XREF: move_okay(int,int)+24↑j
.text:00000000000049A7 48 8B 3C 25 A0 D4 41 00                       mov     rdi, 41D4A0h    ; WINDOW *
.text:00000000000049AF E8 3C F7 FF FF                                call    _winch
.text:00000000000049B4 89 45 F0                                      mov     [rbp+var_10], eax
.text:00000000000049B7
.text:00000000000049B7                               loc_49B7:                               ; CODE XREF: move_okay(int,int)+32↑j
.text:00000000000049B7 8B 45 F0                                      mov     eax, [rbp+var_10]
.text:00000000000049BA 89 45 F4                                      mov     [rbp+var_C], eax
.text:00000000000049BD 83 7D F4 20                                   cmp     [rbp+var_C], 20h ; ' '
.text:00000000000049C1 B1 01                                         mov     cl, 1
.text:00000000000049C3 88 4D EF                                      mov     [rbp+var_11], cl
.text:00000000000049C6 0F 84 0A 00 00 00                             jz      loc_49D6
.text:00000000000049CC 83 7D F4 58                                   cmp     [rbp+var_C], 58h ; 'X'
.text:00000000000049D0 0F 94 C0                                      setz    al
.text:00000000000049D3 88 45 EF                                      mov     [rbp+var_11], al
.text:00000000000049D6
.text:00000000000049D6                               loc_49D6:                               ; CODE XREF: move_okay(int,int)+56↑j
.text:00000000000049D6 8A 45 EF                                      mov     al, [rbp+var_11]
.text:00000000000049D9 24 01                                         and     al, 1
.text:00000000000049DB 0F B6 C0                                      movzx   eax, al
.text:00000000000049DE 48 83 C4 20                                   add     rsp, 20h
.text:00000000000049E2 5D                                            pop     rbp
.text:00000000000049E3 C3                                            retn

I then used a hex editor and changed the follow bytes to all be 0x90:

.text:00000000000049CC 83 7D F4 58                                   cmp     [rbp+var_C], 58h ; 'X'
.text:00000000000049D0 0F 94 C0                                      setz    al
.text:00000000000049D3 88 45 EF                                      mov     [rbp+var_11], al

When I ran the game I was able to go through the wall and go to the flag which was:

rarctf{g4m3_h4ck1ng_f0r_n00b5!-75f8b0}